import logging
import socket
import sqlite3
import sys
import threading
import time
import logging
from logging import handlers
from wsgiref.simple_server import make_server

import requests
import schedule
from spyne import String, Application, ServiceBase, Unicode, rpc, ComplexModel, XmlAttribute, Language, DateTime, Uuid, \
    Long, XmlData, RequestTooLongError, ResourceNotFoundError, RequestNotAllowed, InvalidCredentialsError, \
    Fault
from spyne.const.http import HTTP_202, HTTP_413, HTTP_404, HTTP_405, HTTP_401, HTTP_400, HTTP_500
from spyne.protocol import ProtocolBase
from spyne.protocol.soap import Soap11
from spyne.protocol.xml import XmlDocument
from spyne.server.http import HttpTransportContext
from spyne.util import six
from spyne.util.wsgi_wrapper import WsgiMounter
from suds import Client
from datetime import timezone, timedelta

LOCAL_TZ = timezone(timedelta(hours=8), "Asia/Shanghai")

DB_NAME = "sqlite3.db"
NS = "http://www.ibm.com/maximo"

ORBITA_REQ_URL = "http://172.31.3.1/meaweb/services/BTFM_INCIDENT_M"
MAXIMO_RES_URL = "http://172.31.3.32/Maximo.WcfReponse.Host/SI_Response_OutService.svc?singleWsdl"


# DB定义
class sqliteDB:
    def __init__(self, db):
        self.db = db

    def createConnection(self):
        conn = sqlite3.connect(DB_NAME)
        return conn


# 存入到sqlite中
# 连接db 创建游标
db = sqliteDB(DB_NAME)
conn = db.createConnection()


class BTFM_INCIDENT_OS_INCIDENTType(ComplexModel):
    action = XmlAttribute(String)
    relationship = XmlAttribute(String)
    deleteForInsert = XmlAttribute(String)
    transLanguage = XmlAttribute(Language)
    MAXINTERRORMSG = String
    AFFECTEDPERSON = String
    # 列车号
    ASSETNUM = String
    BTDIAGNOSTIC = String
    BTHEADCODE = String
    BTNEGOTIATIONSTATUS = String
    # 事件发生时间
    BTOCCURRENCEDATE = DateTime
    BTOCCURRENCELOC = String
    BTOPMODE = String
    BTSOURCE = String
    # Orbita系统的AlertID
    BTSOURCEREF = Uuid
    BTSOURCEREF2 = String
    # Orbita系统事件描述
    CLASS = String
    DESCRIPTION = String
    DESCRIPTION_LONGDESCRIPTION = String
    ORGID = String
    # 事件报告时间
    REPORTDATE = DateTime
    REPORTEDBY = String
    # 事件优先级
    REPORTEDPRIORITY = Long
    SITEID = String
    SOURCE = String
    TICKETID = String


class BTFM_INCIDENT_OSSetType(ComplexModel):
    BTINCIDENT = BTFM_INCIDENT_OS_INCIDENTType


class BTFM_INCIDENT_CLASSType(ComplexModel):
    maxvalue = XmlAttribute(String)
    Value = XmlData(Unicode)


class BTFM_INCIDENT_STATUSType(ComplexModel):
    maxvalue = XmlAttribute(String)
    changed = XmlAttribute(String)
    Value = XmlData(Unicode)


class BTFM_INCIDENT_RESType(ComplexModel):
    action = XmlAttribute(String)
    BTSOURCEINSTANCEID = String
    BTSOURCEREF = Uuid
    CLASS = BTFM_INCIDENT_CLASSType
    SITEID = String
    STATUS = BTFM_INCIDENT_STATUSType
    TICKETID = String


class BTFM_INCIDENT_OS_RESSetType(ComplexModel):
    INCIDENT = BTFM_INCIDENT_RESType

# 接收orbita INCIDENT事件，转发至maximo
class BTFM_INCIDENT_OS(ServiceBase):
    creationDateTime = XmlAttribute(DateTime)
    baseLanguage = XmlAttribute(Language)
    transLanguage = XmlAttribute(Language)
    messageID = XmlAttribute(Uuid)
    sourceInstanceID = XmlAttribute(String)
    targetInstanceID = XmlAttribute(String)
    maximoVersion = XmlAttribute(String)

    @rpc(BTFM_INCIDENT_OSSetType, _returns=None)
    def SyncBTFM_INCIDENT_OS(ctx, BTFM_INCIDENT_OSSet):
        try:
            # 按doc 文档取出对应的需要的字段
            assetnum = BTFM_INCIDENT_OSSet.BTINCIDENT.ASSETNUM
            btoccurrencedate = BTFM_INCIDENT_OSSet.BTINCIDENT.BTOCCURRENCEDATE
            btsourceref = BTFM_INCIDENT_OSSet.BTINCIDENT.BTSOURCEREF
            description_longdescription = BTFM_INCIDENT_OSSet.BTINCIDENT.DESCRIPTION_LONGDESCRIPTION
            reportdate = BTFM_INCIDENT_OSSet.BTINCIDENT.REPORTDATE
            reportedpriority = BTFM_INCIDENT_OSSet.BTINCIDENT.REPORTEDPRIORITY
            logging.info("收到Orbita事件---列车号：{}，AlertID：{}，描述：{}，事件发生时间：{}，报告时间：{}，报告优先级：{}"
                         .format(assetnum, btsourceref, description_longdescription, btoccurrencedate.isoformat(),
                                 reportdate, reportedpriority))
            try:
                cursor = conn.cursor()
                # 先将记录存入数据库
                sql_script = "insert into orbita_inc (`assetnum`, `btoccurrencedate`, `btsourceref`,`description_longdescription`," \
                             "`reportdate`,`reportedpriority`) values ('{}','{}','{}','{}','{}','{}')" \
                    .format(assetnum, str(btoccurrencedate.replace(tzinfo=LOCAL_TZ).isoformat()), btsourceref,
                            description_longdescription,
                            str(reportdate.replace(tzinfo=LOCAL_TZ).isoformat()), reportedpriority)
                cursor.execute(sql_script)
                conn.commit()
            except Exception as err:
                logging.error("事件存入数据库时发生错误！Err：%s" % err)
        except Exception as err:
            logging.error("收到事件，但在数据处理时发生错误！Err：%s" % err)
        return None


class PublishBTFM_INCIDENT_OSRes(ServiceBase):
    @rpc(BTFM_INCIDENT_OS_RESSetType, _returns=None)
    def PublishBTFM_INCIDENT_OS_RES(self, BTFM_INCIDENT_OS_RESSet):
        try:
            # resSet = maximo_res_client.factory.create("BTFM_INCIDENT_OS_RESSet")
            # # BTFM_INCIDENT_OS_RESSet.INCIDENT
            # from suds.sax.element import Element
            # incident = resSet.BTINCIDENT
            # incident["BTSOURCEREF"] = BTFM_INCIDENT_OS_RESSet.INCIDENT.BTSOURCEREF
            # incident["SITEID"] = BTFM_INCIDENT_OS_RESSet.INCIDENT.SITEID
            # incident["TICKETID"] = BTFM_INCIDENT_OS_RESSet.INCIDENT.TICKETID
            # incident["BTSOURCEINSTANCEID"] = BTFM_INCIDENT_OS_RESSet.INCIDENT.BTSOURCEINSTANCEID
            # CLASS = Element('CLASS')
            # CLASS.setText(BTFM_INCIDENT_OS_RESSet.INCIDENT.CLASS.Value)
            # CLASS.set("maxvalue", BTFM_INCIDENT_OS_RESSet.INCIDENT.CLASS.maxvalue)
            # incident["CLASS"] = CLASS
            # STATUS = Element('STATUS')
            # STATUS.setText(BTFM_INCIDENT_OS_RESSet.INCIDENT.STATUS.Value)
            # STATUS.set("maxvalue", BTFM_INCIDENT_OS_RESSet.INCIDENT.STATUS.maxvalue)
            # STATUS.set("changed", BTFM_INCIDENT_OS_RESSet.INCIDENT.STATUS.changed)
            # incident["STATUS"] = STATUS
            # maximo_res_client.service.SI_Response_Out(resSet)
            # req = str(maximo_res_client.last_sent())
            # response = str(maximo_res_client.last_received())
            incident = BTFM_INCIDENT_OS_RESSet.INCIDENT
            logging.info("收到Maximo事件响应---状态：{}，AlertID：{}，TicketID：{}，SiteID：{}"
                         .format(incident.STATUS.Value, incident.BTSOURCEREF, incident.TICKETID,
                                 incident.SITEID))
            req = """
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:max="http://www.ibm.com/maximo">
               <soapenv:Header>
                    <Action soapenv:mustUnderstand="1">http://sap.com/xi/WebService/soap1.1</Action>
                </soapenv:Header>
               <soapenv:Body>
                   <max:PublishBTFM_INCIDENT_OS_RES> 
                      <BTFM_INCIDENT_OS_RESSet>
                        <BTINCIDENT action="Replace">
                          <BTSOURCEREF>{}</BTSOURCEREF>
                          <CLASS maxvalue="{}">{}</CLASS>
                          <SITEID>{}</SITEID>
                          <STATUS maxvalue="{}" changed="{}">{}</STATUS>
                          <TICKETID>{}</TICKETID>
                        </BTINCIDENT>
                     </BTFM_INCIDENT_OS_RESSet>
                  </max:PublishBTFM_INCIDENT_OS_RES>
               </soapenv:Body>
            </soapenv:Envelope>
            """.format(incident.BTSOURCEREF, incident.CLASS.maxvalue, incident.CLASS.Value,
                       incident.SITEID, incident.STATUS.maxvalue, incident.STATUS.changed, incident.STATUS.Value,
                       incident.TICKETID)
            headers = {
                'Content-Type': 'text/xml;charset=UTF-8',
                'SoapAction': 'http://sap.com/xi/WebService/soap1.1'
            }
            try:
                res = ''
                res = requests.request("POST", MAXIMO_RES_URL, headers=headers, data=req.encode("UTF-8"))
                logging.info("已将事件响应转发至Orbita：%s" % res.request.body.decode('UTF-8'))
                logging.info("已发送，Orbita响应码：%s, 响应头：%s, 响应内容：\n%s" % (res.status_code, res.headers, res.text))
                status = 'N'
                if res.status_code == 200 or res.status_code == 202:
                    status = 'Y'
                # 将记录存入数据库
                try:
                    cursor = conn.cursor()
                    sql_script = "insert into maximo_inc (`ticket_id`, `status`, `btsourceref`,`site_id`," \
                                 "`class`,`orbita_update`) values ('{}','{}','{}','{}','{}','{}')" \
                        .format(incident.TICKETID, incident.STATUS.Value, incident.BTSOURCEREF,
                                incident.SITEID, incident.CLASS.Value, status)
                    cursor.execute(sql_script)
                    conn.commit()
                except Exception as err:
                    logging.error("事件存入数据库时发生错误！Err：%s" % err)
            except Exception as err:
                logging.error("Maximo事件发送至Orbita时发生错误！Err: %s" % err)
                # 先将记录存入数据库
                try:
                    cursor = conn.cursor()
                    sql_script = "insert into maximo_inc (`ticket_id`, `status`, `btsourceref`,`site_id`," \
                                 "`class`,`orbita_update`) values ('{}','{}','{}','{}','{}','{}')" \
                        .format(incident.TICKETID, incident.STATUS.Value, incident.BTSOURCEREF,
                                incident.SITEID, incident.CLASS.Value, 'N')
                    cursor.execute(sql_script)
                    conn.commit()
                except Exception as err:
                    logging.error("事件存入数据库时发生错误！Err：%s" % err)
        except Exception as err:
            logging.error("收到Maximo事件响应，但在处理数据时发生错误！Err：%s --- 原始数据：%s" % (err, BTFM_INCIDENT_OS_RESSet))
        return None


def getFromDBAndSendToMaximo():
    offset = 0
    page = 100
    while True:
        conn = db.createConnection()
        cursor = conn.cursor()
        sql_query_script = "select * from orbita_inc where `maximo_update`='{}' limit '{}','{}'".format("", offset,
                                                                                                        page)
        result = cursor.execute(sql_query_script)
        size = 0
        for row in result:
            assetnum = row[0]
            btoccurrencedate = row[1]
            btsourceref = row[2]
            description_longdescription = row[3]
            reportdate = row[4]
            reportedpriority = row[5]
            id = row[8]
            # 转换表 查询对应的assertnum
            sql_convert_script = "select `maximo` from orbita_car where orbita = '{}'".format(assetnum)
            cursor1 = conn.cursor()
            res = cursor1.execute(sql_convert_script)
            # 转换后的assertnum
            for row1 in res:
                assetnum = row1[0]
            size += 1
            payload = """
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:max="http://www.ibm.com/maximo">
                <soapenv:Header/>
                <soapenv:Body>
                    <max:CreateBTFM_INCIDENT_M>
                        <max:BTFM_INCIDENT_MSet>
                            <max:INCIDENT>
                                <max:SITEID>SHBRT</max:SITEID>
                                <max:JVDISTIC>FLEETINCIDENT</max:JVDISTIC>
                                <max:ASSETNUM>{}</max:ASSETNUM>
                                <max:REPORTDATE>{}</max:REPORTDATE>
                                <max:DESCRIPTION>{}</max:DESCRIPTION>
                                <max:JVDATEOCC>{}</max:JVDATEOCC>
                                <max:BTSOURCEREF>{}</max:BTSOURCEREF>
                                <max:DESCRIPTION_LONGDESCRIPTION>{}</max:DESCRIPTION_LONGDESCRIPTION>                                             \r\n         " \
                                <max:REPORTEDPRIORITY>{}</max:REPORTEDPRIORITY>
                                <max:JVSOURCE>8.0</max:JVSOURCE>
                            </max:INCIDENT>
                        </max:BTFM_INCIDENT_MSet>
                    </max:CreateBTFM_INCIDENT_M>
                </soapenv:Body>
            </soapenv:Envelope> 
            """.format(assetnum, reportdate, "Orbita:" + str(btsourceref), btoccurrencedate, 
                        btsourceref, description_longdescription, reportedpriority)
            headers = {
                'Content-Type': 'text/xml;charset=UTF-8'
            }
            response = ''
            try:
                response = requests.request("POST", ORBITA_REQ_URL, headers=headers, data=payload.encode("UTF-8"))
            except Exception as e:
                sql_update_script = "update `orbita_inc` set maximo_update = 'N' and `maximo_log` = '{}' where `id` = '{}'".format(
                    e, id)
                cursor2 = conn.cursor()
                cursor2.execute(sql_update_script)
                logging.error("Orbita事件发送至Maximo发生错误！Err：%s" % e)
            finally:
                if response.status_code == 200 or response.status_code == 202:
                    sql_update_script = "update `orbita_inc` set maximo_update = 'Y', maximo_log = 'success' where `id` = '{}'".format(
                        id)
                    cursor2 = conn.cursor()
                    cursor2.execute(sql_update_script)
                    logging.info("Orbita事件已成功发送至Maximo---序号：{}，列车号：{}，AlertID：{}，描述：{}，事件发生时间：{}，报告时间：{}，报告优先级：{}"
                                 .format(id, assetnum, btsourceref, description_longdescription, btoccurrencedate,
                                         reportdate, reportedpriority))
                else:
                    sql_update_script = "update `orbita_inc` set maximo_update = 'N', maximo_log = '{}' where `id` = '{}'".format(
                        response.reason, id)
                    cursor2 = conn.cursor()
                    cursor2.execute(sql_update_script)
                    logging.error("Orbita事件发送至Maximo失败！序号：%s，错误原因：%s" % (id, response.reason))
                conn.commit()
            time.sleep(0.2)
        if size < page:
            offset = 0
            continue
        offset += page


def retrySendToMaximo():
    offset = 0
    page = 100
    while True:
        conn2 = db.createConnection()
        cursor = conn2.cursor()
        sql_query_script = "select * from orbita_inc where `maximo_update`='{}' limit '{}','{}'".format("N", offset,
                                                                                                        page)
        result = cursor.execute(sql_query_script)
        size = 0
        for row in result:
            assetnum = row[0]
            btoccurrencedate = row[1]
            btsourceref = row[2]
            description_longdescription = row[3]
            reportdate = row[4]
            reportedpriority = row[5]
            id = row[8]
            # 转换表 查询对应的assertnum
            sql_convert_script = "select `maximo` from orbita_car where orbita = '{}'".format(assetnum)
            cursor1 = conn2.cursor()
            res = cursor1.execute(sql_convert_script)
            # 转换后的assertnum
            for row1 in res:
                assetnum = row1[0]
            size += 1
            payload = """
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:max="http://www.ibm.com/maximo">
                <soapenv:Header>
                </soapenv:Header>
                <soapenv:Body>
                    <max:CreateBTFM_INCIDENT_M>
                        <max:BTFM_INCIDENT_MSet>
                            <max:INCIDENT>
                                <max:SITEID>SHBRT</max:SITEID>
                                <max:JVDISTIC>FLEETINCIDENT</max:JVDISTIC>
                                <max:ASSETNUM>{}</max:ASSETNUM>
                                <max:REPORTDATE>{}</max:REPORTDATE>
                                <max:DESCRIPTION>{}</max:DESCRIPTION>
                                <max:JVDATEOCC>{}</max:JVDATEOCC>
                                <max:BTSOURCEREF>{}</max:BTSOURCEREF>
                                <max:DESCRIPTION_LONGDESCRIPTION>{}</max:DESCRIPTION_LONGDESCRIPTION>                                             \r\n         " \
                                <max:REPORTEDPRIORITY>{}</max:REPORTEDPRIORITY>
                                <max:JVSOURCE>8.0</max:JVSOURCE>
                            </max:INCIDENT>
                        </max:BTFM_INCIDENT_MSet>
                    </max:CreateBTFM_INCIDENT_M>
                </soapenv:Body>
            </soapenv:Envelope> 
            """.format(assetnum, reportdate, "Orbita:" + str(btsourceref), 
                        btoccurrencedate, btsourceref, description_longdescription, reportedpriority)
            headers = {
                'Content-Type': 'text/xml;charset=UTF-8'
            }
            response = ''
            try:
                response = requests.request("POST", ORBITA_REQ_URL, headers=headers, data=payload.encode("UTF-8"))
            except Exception as e:
                sql_update_script = "update `orbita_inc` set maximo_update = 'N' and `maximo_log` = '{}' where `id` = '{}'".format(
                    e, id)
                cursor2 = conn2.cursor()
                cursor2.execute(sql_update_script)
                logging.error("Orbita事件[重试]发送至Maximo发生错误！Err：%s" % e)
            finally:
                if response.status_code == 200 or response.status_code == 202:
                    sql_update_script = "update `orbita_inc` set maximo_update = 'Y', maximo_log = 'success' where `id` = '{}'".format(
                        id)
                    cursor2 = conn2.cursor()
                    cursor2.execute(sql_update_script)
                    logging.info(
                        "Orbita事件[重试]已成功发送至Maximo---序号：{}，列车号：{}，AlertID：{}，描述：{}，事件发生时间：{}，报告时间：{}，报告优先级：{}"
                            .format(id, assetnum, btsourceref, description_longdescription, btoccurrencedate,
                                    reportdate, reportedpriority))
                else:
                    sql_update_script = "update `orbita_inc` set maximo_update = 'N', maximo_log = '{}' where `id` = '{}'".format(
                        response.reason, id)
                    cursor2 = conn2.cursor()
                    cursor2.execute(sql_update_script)
                conn2.commit()
            time.sleep(0.2)
        if size < page:
            break
        offset += page

    offset = 0
    page = 100
    while True:
        conn2 = db.createConnection()
        cursor = conn2.cursor()
        sql_query_script = "select * from maximo_inc where `orbita_update`='{}' limit '{}','{}'".format("N", offset,
                                                                                                        page)
        result = cursor.execute(sql_query_script)
        size = 0
        for row in result:
            size += 1
            # resSet = maximo_res_client.factory.create("BTFM_INCIDENT_OS_RESSet")
            # # BTFM_INCIDENT_OS_RESSet.INCIDENT
            # from suds.sax.element import Element
            # id = row[0]
            # incident = resSet.BTINCIDENT
            # incident["BTSOURCEREF"] = row[4]
            # incident["SITEID"] = row[5]
            # incident["TICKETID"] = row[1]
            # incident["CLASS"] = row[6]
            # incident["STATUS"] = row[2]
            # maximo_res_client.service.SI_Response_Out(resSet)
            # req = str(maximo_res_client.last_sent())
            # response = str(maximo_res_client.last_received())
            req = """
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:max="http://www.ibm.com/maximo">
                <soapenv:Header>
                    <Action soapenv:mustUnderstand="1">http://sap.com/xi/WebService/soap1.1</Action>
                </soapenv:Header>
               <soapenv:Body>
                    <max:PublishBTFM_INCIDENT_OS_RES> 
                      <BTFM_INCIDENT_OS_RESSet>
                        <BTINCIDENT action="Replace">
                          <BTSOURCEREF>{}</BTSOURCEREF>
                          <CLASS maxvalue="{}">{}</CLASS>
                          <SITEID>{}</SITEID>
                          <STATUS maxvalue="{}" changed="{}">{}</STATUS>
                          <TICKETID>{}</TICKETID>
                        </BTINCIDENT>
                     </BTFM_INCIDENT_OS_RESSet>
                    </max:PublishBTFM_INCIDENT_OS_RES>
               </soapenv:Body>
            </soapenv:Envelope>
            """.format(row[4], "INCIDENT", row[6], row[5], "RESOLVED", "1", row[2], row[1])
            headers = {
                'Content-Type': 'text/xml;charset=UTF-8',
                'SoapAction': 'http://sap.com/xi/WebService/soap1.1'
            }
            res = ''
            status = 'N'
            try:
                res = requests.request("POST", MAXIMO_RES_URL, headers=headers, data=req.encode("UTF-8"))
                logging.info("已将事件响应转发至Orbita：%s" % res.request.body.decode('UTF-8'))
                logging.info("已发送，Orbita响应码：%s, 响应头：%s, 响应内容：\n%s" % (res.status_code, res.headers, res.text))
                if res.status_code == 200 or res.status_code == 202:
                    status = 'Y'
            except Exception as err:
                logging.error("【重试】事件转发至maximo发生错误！Err: %s" % err)
                status = 'N'
            finally:
                try:
                    cursor = conn2.cursor()
                    sql_script = "update `maximo_inc` set orbita_update = '{}' where id = '{}' ".format(status, id)
                    cursor.execute(sql_script)
                    conn2.commit()
                except Exception as err:
                    if status == 'Y':
                        logging.error("【重试】事件转发至maximo成功，但更新数据记录状态时发生错误！Err：%s" % err)
                    else:
                        logging.error("【重试】事件转发至maximo失败！Error: %s" % err)
        if size < page:
            break
        offset += page


def scheduleRetry():
    schedule.every(20).minutes.do(retrySendToMaximo)
    while True:
        schedule.run_pending()


class NoneOutProtocal(ProtocolBase):
    def create_out_string(self, ctx):
        if isinstance(ctx.transport, HttpTransportContext):
            if ctx.in_error is None and ctx.out_error is None:
                del ctx.transport.resp_headers["Content-Type"]
                ctx.transport.resp_code = HTTP_202
                ctx.transport.resp_headers["#status#"] = "HTTP/1.1 202 Accepted"

    def fault_to_http_response_code(self, fault):
        """Special function to convert native Python exceptions to Http response
        codes.
        """

        if isinstance(fault, RequestTooLongError):
            return HTTP_413

        if isinstance(fault, ResourceNotFoundError):
            return HTTP_404

        if isinstance(fault, RequestNotAllowed):
            return HTTP_405

        if isinstance(fault, InvalidCredentialsError):
            return HTTP_401

        if isinstance(fault, Fault) and (fault.faultcode.startswith('Client.')
                                         or fault.faultcode == 'Client'):
            return HTTP_400

        return HTTP_500


class CustomSoap(Soap11):
    def from_unicode(self, class_, string, *args, **kwargs):
        if string is None:
            return None

        # if not six.PY2:
        #    assert isinstance(string, str), \
        #        "Invalid type passed to `from_unicode`: {}".format(
        #                                         (class_, type(string), string))

        cls_attrs = self.get_cls_attrs(class_)

        if isinstance(string, six.string_types) and len(string) == 0 and \
                cls_attrs.empty_is_none:
            return None

        handler = self._from_unicode_handlers[class_]
        return handler(class_, string.strip(), *args, **kwargs)


app1 = Application([BTFM_INCIDENT_OS],
                   name="BTFM_INCIDENT_OS",
                   tns=NS,
                   in_protocol=CustomSoap(validator="soft", remove_blank_text=True),
                   out_protocol=NoneOutProtocal()
                   )

app2 = Application([PublishBTFM_INCIDENT_OSRes],
                   name="PublishBTFM_INCIDENT_OS_RES",
                   tns=NS,
                   in_protocol=XmlDocument(),
                   out_protocol=NoneOutProtocal()
                   )
maximo_res_client = Client(MAXIMO_RES_URL)


# orbita_req_client = Client(ORBITA_REQ_URL)

def get_host_ip():
    ip = 'localhost'
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
        s.connect(('8.8.8.8', 8080))
        ip = s.getsockname()[0]
    return ip


def log_init():
    import os
    os.makedirs("logs", mode=0o777, exist_ok=True)
    # 输出的格式
    formatter = logging.Formatter(
        fmt='%(asctime)s - [%(levelname)s] %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')

    # 控制台的输出
    ch = logging.StreamHandler()
    ch.setFormatter(formatter)

    # log文件的记录
    th = handlers.TimedRotatingFileHandler(filename='logs/info.log', when='D', backupCount=3, encoding='utf-8')
    th.setFormatter(formatter)

    eh = handlers.TimedRotatingFileHandler(filename='logs/err.log', when='D', backupCount=3, encoding='utf-8')
    eh.setFormatter(formatter)

    # 设置过滤条件
    info_filter = logging.Filter()
    info_filter.filter = lambda record: record.levelno < logging.WARNING  # 设置过滤等级
    err_filter = logging.Filter()
    err_filter.filter = lambda record: record.levelno >= logging.WARNING

    th.addFilter(info_filter)
    eh.addFilter(err_filter)

    logging.basicConfig(level=logging.INFO, handlers=[ch, th, eh], format='%(asctime)s - [%(levelname)s] %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')


if __name__ == '__main__':
    log_init()
    root = WsgiMounter({"orbita": app1, "maximo": app2})
    host = "0.0.0.0"
    port = 8080
    server = make_server(host, port, root)
    getDataThread = threading.Thread(target=getFromDBAndSendToMaximo)
    getDataThread.start()
    retryThread = threading.Thread(target=scheduleRetry)
    retryThread.start()
    ip = get_host_ip()
    logging.info("listening to http://%s:%d" % (ip, port))
    logging.info("Orbita create INCIDENT:  http://%s:%d/orbita" % (ip, port))
    logging.info("Maximo INCIDENT Response: http://%s:%d/maximo" % (ip, port))
    sys.exit(server.serve_forever())
